#ifndef __LINUX_GENERIC_CHIP_H__
#define __LINUX_GENERIC_CHIP_H__

#include "linux/compiler.h"
#include "linux/list.h"
#include "linux/irqdomain.h"
#include "linux/io.h"
#include "linux/irq.h"
#include "linux/irqhandler.h"
#include "linux/interrupt.h"

enum irq_gc_flags
{
    IRQ_GC_INIT_MASK_CACHE = 1 << 0,
    IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
    IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2,
    IRQ_GC_NO_MASK = 1 << 3,
    IRQ_GC_BE_IO = 1 << 4,
};

struct irq_chip_regs
{
    unsigned long enable;
    unsigned long disable;
    unsigned long mask;
    unsigned long ack;
    unsigned long eoi;
    unsigned long type;
    unsigned long polarity;
};

struct irq_chip_type
{
    struct irq_chip chip;
    struct irq_chip_regs regs;
    irq_flow_handler_t handler;
    u32 type;
    u32 mask_cache_priv;
    u32 *mask_cache;
};

struct irq_chip_generic
{
    //raw_spinlock_t lock;
    void __iomem *reg_base;
    u32 (*reg_readl)(void __iomem *addr);
    void (*reg_writel)(u32 val, void __iomem *addr);
    void (*suspend)(struct irq_chip_generic *gc);
    void (*resume)(struct irq_chip_generic *gc);
    unsigned int irq_base;
    unsigned int irq_cnt;
    u32 mask_cache;
    u32 type_cache;
    u32 polarity_cache;
    u32 wake_enabled;
    u32 wake_active;
    unsigned int num_ct;
    void *private;
    unsigned long installed;
    unsigned long unused;
    struct irq_domain *domain;
    struct list_head list;
    struct irq_chip_type chip_types[0];
};


#ifdef CONFIG_SMP
static inline void irq_gc_lock(struct irq_chip_generic *gc)
{
	raw_spin_lock(&gc->lock);
}

static inline void irq_gc_unlock(struct irq_chip_generic *gc)
{
	raw_spin_unlock(&gc->lock);
}
#else
static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
#endif

#define irq_gc_lock_irqsave(gc, flags) // raw_spin_lock_irqsave(&(gc)->lock, flags)

#define irq_gc_unlock_irqrestore(gc, flags) // raw_spin_unlock_irqrestore(&(gc)->lock, flags)

static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
{
	return container_of(d->chip, struct irq_chip_type, chip);
}

u32 irq_reg_readl(struct irq_chip_generic *gc, int reg_offset);
void irq_reg_writel(struct irq_chip_generic *gc, u32 val, int reg_offset);
void irq_gc_noop(struct irq_data *d);
void irq_gc_mask_disable_reg(struct irq_data *d);
void irq_gc_mask_set_bit(struct irq_data *d);
void irq_gc_mask_clr_bit(struct irq_data *d);
void irq_gc_unmask_enable_reg(struct irq_data *d);
void irq_gc_ack_set_bit(struct irq_data *d);
void irq_gc_ack_clr_bit(struct irq_data *d);
void irq_gc_mask_disable_reg_and_ack(struct irq_data *d);
void irq_gc_eoi(struct irq_data *d);
int irq_gc_set_wake(struct irq_data *d, unsigned int on);
struct irq_chip_generic * irq_alloc_generic_chip(char *name, int num_ct, unsigned int irq_base, void __iomem *reg_base, irq_flow_handler_t handler);
void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, enum irq_gc_flags flags, unsigned int clr, unsigned int set);
#endif

